package my.simplecalculator;

import java.util.regex.*;

public class CopyOfCalculatorWithWord{
	final String numberPtn = "^\\d+(\\.\\d+)?$";	
	final String opPtn = "[\\+\\-\\*\\/\\=]";
	
	private enum Stat {undefinedStat, number, point, op};	// 미정의, 수, 소수점, 연산자	
	private enum OpStat {nonOperation, plus, minus, multiply, divide, equal};	// + or - or * or / or =
	
	private Stat p, q, r;			// 초기 상태, 이전상태, 현재상태
	private OpStat op; 						// 이전 연산자
	
	private String lvalue, rvalue;		// 결과값, 임시값
	
	public String expr, result;			// 계산 식, 계산값
	
	public CopyOfCalculatorWithWord() {
		super();
		init();
	}
	
	/**
	 * 멤버를 초기화
	 */
	protected void init(){
		p=Stat.undefinedStat;
		q=Stat.undefinedStat;
		r=Stat.undefinedStat;
		
		op = OpStat.nonOperation;
		
		expr="";
		result="";
		lvalue="";
		rvalue="";
	}
		
	/** 
	 * 입력된 단어가 숫자인지 확인
	 * boolean isNumber(String input)
	 * @param input
	 * @return input이 정수이거나 실수이면 true
	 */
	protected boolean isNumber(String input){
		input = input.trim();
		boolean result = Pattern.matches(numberPtn, input);
		return result;
	}
	
	/**
	 * 입력된 단어가 연산자인지 확인
	 * boolean isOp(String input)
	 * @param word
	 * @return input이 "+" or "-" or "*" or "/" or "=" 이면 true
	 */
	protected boolean isOp(String word){
		boolean result=false;
		word = word.trim();		
		result = Pattern.matches(opPtn, word);
		return result;
	}
	
	/**
	 * 입력된 단어가 소숫점인지 확인
	 * @param word
	 * @return
	 */
	protected boolean isPoint(String word){
		boolean result=false;
		word = word.trim();		
		result = Pattern.matches("\\d*\\.\\d*", word);
		return result;
	}

	/**
	 * 입력된 단어가 어느 Stat인지 확인
	 * Stat whichStat(String input)
	 * @param word
	 * @return input이 어느 Stat인지 확인 (undefined, number, op)
	 */
	private Stat whichStat(String word){
		Stat resultStat = Stat.undefinedStat;
		
		word = word.trim();
		
		if(isNumber(word))
		{
			resultStat = Stat.number;			
		}
		else if(isPoint(word)){
			resultStat = Stat.point;
		}
		else if(isOp(word)){
			resultStat = Stat.op;			
		}
		return resultStat;
	}
	
	/**
	 * 입력된 연산자의 종류를 확인
	 * @param words
	 * @return
	 */
	private OpStat whichOp(String words){
		OpStat resultStat = OpStat.nonOperation;
		if(isOp(words)){ 
			words = words.trim();
			if(words.equals("+")){
				resultStat = OpStat.plus;
			}
			else if(words.equals("-")){
				resultStat = OpStat.minus;
			}
			else if(words.equals("*"))	{
				resultStat = OpStat.multiply;
			}
			else if(words.equals("/"))	{
				resultStat = OpStat.divide;
			}
			else if(words.equals("=")){
				resultStat = OpStat.equal;
			}
		}
		return resultStat;
	}
		
	/**
	 * 계산 결과를 result변수에 할당함
	 */	
	private void calculate(String lValue, String rValue, OpStat op)
	{

		if(lvalue==null || lvalue.isEmpty() || rvalue==null || rvalue.isEmpty()) return;
		
		double leftVal = Double.parseDouble(lValue);
		double rightVal = Double.parseDouble(rValue);
		switch(op){
		case plus:		
			result = String.valueOf(leftVal+rightVal);
			break;
		case minus:		
			result = String.valueOf(leftVal-rightVal);
			break;
		case multiply:		
			result = String.valueOf(leftVal*rightVal);
			break;
		case divide:		
			result = String.valueOf(leftVal/rightVal);
			break;
		case equal:		
			
			break;
			
		}
	}	
	
	/*
	 * public method 
	*/
	
	
	/**
	 * 단어 단위로 입력값을 받아 계산 값을 result에 할당
	 * void input(String string)
	 * @param word
	 */	
	public void inputWord(String word) {		
		word = word.trim();
					
		r = whichStat(word);
//		System.out.println("["+word +"]("+r+")");
		
		switch(r){
		case number:
			if(!result.isEmpty()) lvalue = result;			
			rvalue += word;
			break;
		case point:
			rvalue += word;
			r=Stat.number;
			break;
		case op:			
			calculate(lvalue, rvalue, op);
			lvalue = rvalue;
			op = whichOp(word);
			rvalue="";			
			break;
		}
		
		if(op!=OpStat.equal) expr += word;		
		
//		testPrint();	//
		if(q != r) {			
			p = q;
			q = r;
		}
	}
	
	// 테스트용 출력	
	public void testPrint(){
		System.out.print("["+expr+"]");		
//		System.out.println("lvalue:" + lvalue + "\trvalue: " + rvalue);
//		System.out.println("p: " + p + "\tq: " + q + "\tr: " + r);
		System.out.println(" = "+result);
		System.out.println();
	}
}
